﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using _5E.Utils.DbHelper.EasySQL.Creator;

namespace _5E.Utils.DbHelper.EasySQL
{
    /// <summary>
    /// 程序说明：SQL创建者
    /// 创建作者：ahl5esoft
    /// 创建时间：2012-04-16
    /// </summary>
    internal class EasySQL
    {
        #region 变量

        public const string WHERE_SEPARATOR = " AND ";

        public const string EQUAL_FORMAT = "{0} = :{1}";

        private const string ELEMENT_PK_NAME = "pk";

        private const string ELEMENT_FK_NAME = "fk";

        private const string ELEMENT_OTHER_NAME = "column";

        private string m_TableName = null;

        private string[] m_PKPropertyNames = new string[] { };

        #endregion

        #region 实例属性

        private string[] m_FKPropertyNames = new string[] { };
        public string[] FKPropertyNames { get { return this.m_FKPropertyNames; } }

        private string[] m_OtherPropertyNames = new string[] { };
        public string[] OtherPropertyNames { get { return this.m_OtherPropertyNames; } }

        private Dictionary<string, string> m_AllColumns = new Dictionary<string, string>();
        public Dictionary<string, string> AllColumns { get { return this.m_AllColumns; } }

        private BaseCreator m_QueryCreator = null;
        public BaseCreator QueryCreator { get { return this.m_QueryCreator; } }

        private BaseCreator m_InsertCreator;
        public BaseCreator InsertCreator { get { return this.m_InsertCreator; } }

        private BaseCreator m_UpdateCreator = null;
        public BaseCreator UpdateCreator { get { return this.m_UpdateCreator; } }

        private BaseCreator m_DeleteCreator = null;
        public BaseCreator DeleteCreator { get { return this.m_DeleteCreator; } }

        private string m_PKWhere = null;
        public string PKWhere
        {
            get
            {
                if (null == this.m_PKWhere)
                {
                    var pks = Array.ConvertAll(this.m_PKPropertyNames,
                        propertyName => string.Format("={0}", propertyName));
                    this.m_PKWhere = string.Join(WHERE_SEPARATOR, pks);
                }
                return this.m_PKWhere;
            }
        }

        #endregion

        #region 构造函数

        private EasySQL() { }

        public EasySQL(string mappingPath)
        {
            this.CheckAndParseMappingPath(mappingPath);
            this.InitSQLCreator();
        }

        #endregion

        #region 实例方法

        private void CheckAndParseMappingPath(string mappingPath)
        {
            var filePath = AppDomain.CurrentDomain.BaseDirectory.Replace("bin\\Debug\\", mappingPath);
            var exist = File.Exists(filePath);
            if (exist)
            {
                this.ParseMapping(filePath);
            }
            else
            {
                throw new ArgumentNullException("实体映射路径不正确!");
            }
        }

        private void ParseMapping(string filePath)
        {
            var mapping = XElement.Load(filePath);
            this.m_TableName = mapping.Name.LocalName;
            this.m_PKPropertyNames = this.GetColumnAndPropertyNames(mapping, ELEMENT_PK_NAME);
            this.m_FKPropertyNames = this.GetColumnAndPropertyNames(mapping, ELEMENT_FK_NAME);
            this.m_OtherPropertyNames = this.GetColumnAndPropertyNames(mapping, ELEMENT_OTHER_NAME);
        }

        private string[] GetColumnAndPropertyNames(XElement root, string elementName)
        {
            var columns = root.Elements(elementName);
            var propertyNames = new List<string>();
            foreach (var column in columns)
            {
                var propertyName = column.Attribute("property").Value;
                propertyNames.Add(propertyName);
                this.m_AllColumns.Add(propertyName, column.Attribute("name").Value);
            }
            return propertyNames.ToArray();
        }

        private void InitSQLCreator()
        {
            this.m_QueryCreator = new QueryCreator(this.m_TableName, this.m_AllColumns);
            this.m_InsertCreator = new InsertCreator(this.m_TableName, this.m_AllColumns);
            this.m_UpdateCreator = new UpdateCreator(this.m_TableName, this.m_AllColumns);
            this.m_DeleteCreator = new DeleteCreator(this.m_TableName, this.m_AllColumns);
        }

        #endregion

        #region 静态方法

        public static string ToEqualString(string columnName, string propertyName)
        {
            var equalString = string.Format(EQUAL_FORMAT, columnName, propertyName);
            return equalString;
        }

        #endregion
    }
}
